package com.weir.resources.permissions.map;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 公共路线接口方法，计算实际距离。
 */
public class MapDistanceUtil {

	private static final String HOSTARR = "http://restapi.amap.com/v3/geocode/regeo";
	private static final String HOST = "https://restapi.amap.com/v3/distance";
// private static final String HOST = "http://122.114.79.163:7770/v3/distance";
	private static final String KEY = "761e73b6188fb868feee5b558dcbcd7a";

	private static ObjectMapper mapper = new ObjectMapper();
	/**
	 * 参数:（出发点数组、目的点） 格式：经度,纬度 返回: { "status": "1", "info": "OK", "infocode":
	 * "10000", "results": [{ //结果数组 "origin_id": "1", //第一个起点 "dest_id": "1",
	 * //目的地 "distance": "261278", //距离（米） "duration": "14280" //预计时间（秒） }] }
	 */
	public static String mapDistanceMethod(String[] origins,
			String destination) {
		String responseEntity = null;
		for (int i = 0; i < 5 && responseEntity == null; i++) {
			responseEntity = mapDistance(origins, destination);
		}
		return responseEntity;
	}

	public static String getLocationAddr(String location) {
		List<NameValuePair> list = new LinkedList<>();
		list.add(new BasicNameValuePair("key", KEY));
		list.add(new BasicNameValuePair("output", "JSON"));
		list.add(new BasicNameValuePair("location", location));
		String responseEntity = null;
		String addr = "";
		try {
			HttpGet httpGet = new HttpGet(
					new URIBuilder(HOSTARR).setParameters(list).build());
			httpGet.setConfig(
					RequestConfig.custom().setConnectTimeout(2000).build());
			HttpResponse response = HttpClients.createDefault()
					.execute(httpGet);
			responseEntity = EntityUtils.toString(response.getEntity(),
					"UTF-8");
//			JSONObject jsonObject = JSON.parseObject(responseEntity);
			LinkedHashMap<String, Object> readValue = mapper.readValue(responseEntity, LinkedHashMap.class);
			LinkedHashMap<String, Object> readValue2 = (LinkedHashMap<String, Object>) readValue.get("regeocode");
			addr = readValue2.get("formatted_address").toString();
//			LinkedHashMap<String, Object> readValue4 = (LinkedHashMap<String, Object>) readValue3.get("building");
//			String name = readValue4.get("name").toString();
//			System.out.println(responseEntity);
//			addr = jsonObject.getJSONObject("regeocode")
//					.getString("formatted_address");
//			try {
//				addr = jsonObject.getJSONObject("regeocode")
//						.getJSONObject("addressComponent").getJSONObject("building")
//						.getString("name");
//			} catch (Exception e) {
//			}
//			if (addr.equals("[]")) {
//				addr = jsonObject.getJSONObject("regeocode")
//						.getString("formatted_address");
//				if (addr.indexOf("省") > 0) {
//					addr = addr.substring(addr.indexOf("省") + 1, addr.length());
//				}
//				if (addr.indexOf("市") > 0) {
//					addr = addr.substring(addr.indexOf("市") + 1, addr.length());
//				}
//			}
//System.out.println("-------响应结果-------\n" + addr);
		} catch (Exception e) {
			if (e instanceof ConnectTimeoutException) {
				System.out.println("-------请求超时-------");
			} else {
				e.printStackTrace();
			}
		}
		return addr;
	}

	private static String mapDistance(String[] origins, String destination) {
		StringBuilder originBuilder = new StringBuilder();
		for (int i = 0; i < origins.length; i++) {
			originBuilder.append(origins[i]);
			if (i < origins.length - 1) {
				originBuilder.append("|");
			}
		}
		List<NameValuePair> list = new LinkedList<>();
		list.add(new BasicNameValuePair("key", KEY));
		list.add(new BasicNameValuePair("output", "JSON"));
		list.add(new BasicNameValuePair("origins", originBuilder.toString()));
		list.add(new BasicNameValuePair("destination", destination));
		String responseEntity = null;
		try {
			HttpGet httpGet = new HttpGet(
					new URIBuilder(HOST).setParameters(list).build());
			httpGet.setConfig(
					RequestConfig.custom().setConnectTimeout(2000).build());
			HttpResponse response = HttpClients.createDefault()
					.execute(httpGet);
			responseEntity = EntityUtils.toString(response.getEntity(),
					"UTF-8");
//System.out.println("-------距离测量响应结果-------\n" + responseEntity);
		} catch (Exception e) {
			if (e instanceof ConnectTimeoutException) {
				System.out.println("-------请求超时-------");
			} else {
				e.printStackTrace();
			}
		}
		return responseEntity;
	}

	public static void main(String[] args)
			throws Exception {
//		System.out.println(getLocationAddr("113.242439,35.1863620"));
//		getOut("C:\\Users\\Administrator\\Desktop\\车辆去过的地点.xlsx","C:\\Users\\Administrator\\Desktop\\车辆去过的地点11.xlsx");
		List<String> readCsvs = new ArrayList<>();
		readfile("/Users/weir/Downloads/11", readCsvs);
//		readfile("C:\\Users\\Administrator\\OneDrive\\桌面\\11", readCsvs);
		getOutCSV(readCsvs, outFile);
	}

	private static void getOut(String in, String out)
			throws FileNotFoundException {
		OutputStream outputStream = new FileOutputStream(out);
		InputStream iStream = new FileInputStream(in);
		List<Object> doReadSync = EasyExcelFactory.read(iStream,
				new Sheet(1, 1));
		ExcelWriter writer = EasyExcelFactory.getWriter(outputStream);
		List<String> head = Arrays.asList("经度", "纬度", "地址");

		Sheet initSheet = new Sheet(1, 0);
		initSheet.setSheetName("sheet");
		// 设置自适应宽度
		initSheet.setAutoWidth(Boolean.TRUE);
		List<List<String>> list = new ArrayList<>();
		head.forEach(h -> list.add(Collections.singletonList(h)));
		initSheet.setHead(list);
		List<List<Object>> list3 = new ArrayList<>();
		for (Object object : doReadSync) {
			List<Object> list2 = (List<Object>) object;
//			double[] lngAndLat = GeoHashUtils
//					.toLngAndLat(list2.get(0).toString());
			String address = getLocationAddr(list2.get(0) + "," + list2.get(1));
//			String address = getLocationAddr(lngAndLat[0] + "," + lngAndLat[1]);
			list2.add(address);
			list3.add(list2);
		}
		try {
			writer.write1(list3, initSheet);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (writer != null) {
					writer.finish();
				}
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println("222--------------------------");
	}

	private static final String outFile = "/Users/weir/Downloads/22.xlsx";
//	private static final String outFile = "C:\\Users\\Administrator\\OneDrive\\桌面\\11\\22.xlsx";

	private static void getOutCSV(List<String> readCsv, String out)
			throws Exception {
		OutputStream outputStream = new FileOutputStream(out);
//		InputStream iStream = new FileInputStream(in);
//		List<Object> doReadSync = EasyExcelFactory.read(iStream,
//				new Sheet(1, 1));
		ExcelWriter writer = EasyExcelFactory.getWriter(outputStream);
//		List<String> head = Arrays.asList("车辆id","geohash", "距离米","地址");
		List<String> head = Arrays.asList("id","vehicle_id","store_id","geohash","distance",	"ad_code","address"	,"total_duration",	"park_count",	"month");

		Sheet initSheet = new Sheet(1, 0);
		initSheet.setSheetName("sheet");
		// 设置自适应宽度
		initSheet.setAutoWidth(Boolean.TRUE);
		List<List<String>> list = new ArrayList<>();
		head.forEach(h -> list.add(Collections.singletonList(h)));
		initSheet.setHead(list);
		List<List<Object>> list3 = new ArrayList<>();
		
		
		// 每500条数据开启一条线程
        int threadSize = 5000;
        // 总数据条数
        int dataSize = readCsv.size();
        // 线程数
        int threadNum = dataSize / threadSize + 1;
        // 定义标记,过滤threadNum为整数
        boolean special = dataSize % threadSize == 0;
        // 创建一个线程池
        ExecutorService exec = Executors.newFixedThreadPool(threadNum);
     // 定义一个任务集合
        List<Callable<List<List<Object>>>> tasks = new ArrayList<Callable<List<List<Object>>>>();
        Callable<List<List<Object>>> task = null;
        List<String> cutList = null;
     // 确定每条线程的数据
        for (int i = 0; i < threadNum; i++) {
			if (i == threadNum - 1) {
                if (special) {
                    break;
                }
                cutList = readCsv.subList(threadSize * i, dataSize);
            } else {
                cutList = readCsv.subList(threadSize * i, threadSize * (i + 1));
            }
            // System.out.println("第" + (i + 1) + "组：" + cutList.toString());
            final List<String> listStr = cutList;
            task = new Callable<List<List<Object>>>() {

                @Override
                public List<List<Object>> call() throws Exception {
                	List<List<Object>> ll = new ArrayList<>();
                	for (String str : listStr) {
            			String[] as = str.split(",");
//            			System.out.println("-----------------" + Arrays.deepToString(as));
            			if (as.length <= 1) {
            				continue;
            			}
            			if (as[0].equals("geohash")) {
            				continue;
            			}
            			List<Object> list2 = new ArrayList<>();
            			list2.add(as[0]);
            			list2.add(as[1]);
            			list2.add(as[2]);
            			list2.add(as[3]);
            			list2.add(as[4]);
            			list2.add(as[5]);
            			list2.add(as[6]);
            			list2.add(as[7]);
            			list2.add(as[8]);
            			list2.add(as[9]);
            			double[] lngAndLat = GeoHashUtils
            					.toLngAndLat(as[3]);
            			String address = getLocationAddr(lngAndLat[0] + "," + lngAndLat[1]);
//            			String address = getLocationAddr(as[0] + "," + as[1]);
            			list2.add(address);
            			ll.add(list2);
            		}
                	return ll;
                }
            };
            // 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
            tasks.add(task);
        }
        List<Future<List<List<Object>>>> results = exec.invokeAll(tasks);
        for (Future<List<List<Object>>> future : results) {
            List<List<Object>> list2 = future.get();
            list3.addAll(list2);
        }
        // 关闭线程池
        exec.shutdown();
		
		
		
//		for (String str : readCsv) {
//			String[] as = str.split(",");
//			System.out.println("-----------------" + Arrays.deepToString(as));
//			if (as.length <= 1) {
//				continue;
//			}
//			if (as[0].equals("geohash")) {
//				continue;
//			}
//			List<Object> list2 = new ArrayList<>();
//			list2.add(as[0]);
//			list2.add(as[1]);
//			list2.add(as[2]);
//			double[] lngAndLat = GeoHashUtils
//					.toLngAndLat(as[1]);
//			String address = getLocationAddr(lngAndLat[0] + "," + lngAndLat[1]);
////			String address = getLocationAddr(as[0] + "," + as[1]);
//			list2.add(address);
//			list3.add(list2);
//		}
        
//		for (Object object : doReadSync) {
//			List<Object> list2 = (List<Object>) object;
//			double[] lngAndLat = GeoHashUtils
//					.toLngAndLat(list2.get(0).toString());
//			String address = getLocationAddr(lngAndLat[0] + "," + lngAndLat[1]);
//			list2.add(address);
//			list3.add(list2);
//		}
		try {
			writer.write1(list3, initSheet);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (writer != null) {
					writer.finish();
				}
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		System.out.println("end--------------------------");
	}

	/**
	 * 读取某个文件夹下的所有文件
	 */
	public static boolean readfile(String filepath, List<String> readCsvs) {
		try {

			File file = new File(filepath);
			if (!file.isDirectory()) {
				String fileName = file.getName();
		        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
		        if (!suffix.equals("csv")) {
					return false;
				}
//				System.out.println("文件");
//				System.out.println("path=" + file.getPath());
//				System.out.println("absolutepath=" + file.getAbsolutePath());
//				System.out.println("name=" + file.getName());
				List<String> readCsv = readCsv(file);
				readCsvs.addAll(readCsv);
//				System.out.println(readCsv.toString());
//				getOutCSV(readCsv, outFile);

			} else if (file.isDirectory()) {
				System.out.println("文件夹");
				String[] filelist = file.list();
				for (int i = 0; i < filelist.length; i++) {
					File readfile = new File(filepath + "/" + filelist[i]);
					if (!readfile.isDirectory()) {
//						System.out.println("path=" + readfile.getPath());
//						System.out.println(
//								"absolutepath=" + readfile.getAbsolutePath());
//						System.out.println("name=" + readfile.getName());
						String fileName = readfile.getName();
				        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
				        if (!suffix.equals("csv")) {
							continue;
						}
						List<String> readCsv = readCsv(readfile);
						readCsvs.addAll(readCsv);
//						System.out.println(readCsv.toString());
//						getOutCSV(readCsv, outFile);
//						break;
					} else if (readfile.isDirectory()) {
						readfile(filepath + "/" + filelist[i], readCsvs);
					}
				}

			}

//			getOutCSV(readCsvs, outFile);
		} catch (Exception e) {
			System.out.println("readfile()   Exception:" + e.getMessage());
		}
		return true;
	}

	public static List<String> readCsv(File file) {
		List<String> dataList = new ArrayList<>();
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(file));
			String line = "";
			while ((line = br.readLine()) != null) {
				dataList.add(line);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return dataList;
	}
}